﻿// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
#pragma once

#include "..\DeviceResources.h"
#include "ShaderStructures.h"
#include "..\Common\StepTimer.h"
#include "BasicCamera.h"
#include "DataModel\Forecast.h"
#include "LonLatController.h"
#include "Pin.h"

namespace Weathr
{
    // Renders the 3D scene.
    class SceneRenderer
    {
    public:
        explicit SceneRenderer(const std::shared_ptr<DeviceResources>& deviceResources);
        void CreateDeviceDependentResources();
        void CreateWindowSizeDependentResources();
        void ReleaseDeviceDependentResources();
        void Update(DX::StepTimer const& timer);
        void Render();

    private:
        // Loads resources for rendering the Earth
        concurrency::task<void> LoadEarthResourcesAsync();
        // Loads resources for rendering the starfield
        concurrency::task<void> LoadStarfieldResourcesAsync();
        // Loads resources for rendering clouds
        concurrency::task<void> LoadCloudResourcesAsync();

        // Renders the Earth
        void RenderEarth();
        // Renders the starfield
        void RenderStarfield();
        // Renders the clouds
        void RenderClouds();

        // Determines whether the provided 2D coordinates pass through the unit sphere.
        bool PinHitTest(float x, float y, LatLon& result);

        // Resources for Earth geometry
        struct
        {
            // Direct3D resources
            Microsoft::WRL::ComPtr<ID3D11InputLayout>           m_inputLayout;        // mesh vertex input layout
            Microsoft::WRL::ComPtr<ID3D11Buffer>                m_vertexBuffer;       // mesh vertex buffer
            Microsoft::WRL::ComPtr<ID3D11Buffer>                m_indexBuffer;        // mesh index buffer
            Microsoft::WRL::ComPtr<ID3D11VertexShader>          m_vertexShader;       // vertex shader
            Microsoft::WRL::ComPtr<ID3D11PixelShader>           m_pixelShader;        // pixel shader
            Microsoft::WRL::ComPtr<ID3D11Texture2D>             m_texture;            // color texture
            Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>    m_textureSRV;         // color texture view
            Microsoft::WRL::ComPtr<ID3D11SamplerState>          m_sampler;            // color texture sampler
            Microsoft::WRL::ComPtr<ID3D11Texture2D>             m_normals;            // normal map texture
            Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>    m_normalSRV;          // normal map texture view
            Microsoft::WRL::ComPtr<ID3D11SamplerState>          m_normalSampler;      // normal map sampler
            Microsoft::WRL::ComPtr<ID3D11Buffer>                m_vsConstantBuffer;   // vertex shader constant buffer resource
            Microsoft::WRL::ComPtr<ID3D11Buffer>                m_psConstantBuffer;   // pixel shader constant buffer resource

            // System resources
            ModelViewProjectionConstantBuffer                   m_vsConstantBufferData;
            LightConstantBuffer                                 m_psConstantBufferData;
            unsigned int                                        m_indexCount;         // mesh index count

        } m_earthResources;

        // Resources for star geometry
        struct
        {
            // Direct3D resources
            Microsoft::WRL::ComPtr<ID3D11InputLayout>           m_inputLayout;        // mesh vertex input layout
            Microsoft::WRL::ComPtr<ID3D11Buffer>                m_vertexBuffer;       // mesh vertex buffer
            Microsoft::WRL::ComPtr<ID3D11Buffer>                m_indexBuffer;        // mesh index buffer
            Microsoft::WRL::ComPtr<ID3D11VertexShader>          m_vertexShader;       // vertex shader
            Microsoft::WRL::ComPtr<ID3D11PixelShader>           m_pixelShader;        // cloud pixel shader
            Microsoft::WRL::ComPtr<ID3D11Texture2D>             m_texture;            // color texture
            Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>    m_textureSRV;         // color texture view
            Microsoft::WRL::ComPtr<ID3D11SamplerState>          m_sampler;            // color texture sampler
            Microsoft::WRL::ComPtr<ID3D11Buffer>                m_vsConstantBuffer;   // constant buffer resource
            Microsoft::WRL::ComPtr<ID3D11BlendState>            m_blendState;

            // System resources
            ModelViewProjectionCameraConstantBuffer             m_vsConstantBufferData;
            unsigned int                                        m_indexCount;         // mesh index count

        } m_starfieldResources;

        // Resources for cloud geometry
        struct
        {
            // Direct3D resources.
            Microsoft::WRL::ComPtr<ID3D11InputLayout>           m_inputLayout;        // mesh vertex input layout
            Microsoft::WRL::ComPtr<ID3D11Buffer>                m_vertexBuffer;       // mesh vertex buffer
            Microsoft::WRL::ComPtr<ID3D11Buffer>                m_indexBuffer;        // mesh index buffer
            Microsoft::WRL::ComPtr<ID3D11VertexShader>          m_vertexShader;       // vertex shader
            Microsoft::WRL::ComPtr<ID3D11PixelShader>           m_pixelShader;        // cloud pixel shader
            Microsoft::WRL::ComPtr<ID3D11Texture2D>             m_staticMap;          // color texture
            Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>    m_staticMapSRV;       // color texture view
            Microsoft::WRL::ComPtr<ID3D11SamplerState>          m_sampler;            // color texture sampler
            Microsoft::WRL::ComPtr<ID3D11Buffer>                m_psConstantBuffer;   // pixel shader constant buffer resource
            Microsoft::WRL::ComPtr<ID3D11BlendState>            m_blendState;
            Microsoft::WRL::ComPtr<ID3D11DepthStencilState>     m_depthStencilState;  // used to disable depth testing

            // System resources
            CloudParametersConstantBuffer                       m_psConstantBufferData;
            unsigned int                                        m_indexCount;         // mesh index count
            BasicTimer^ m_timer;

        } m_cloudResources;

        std::shared_ptr<ExceptionPolicy> m_exceptionPolicy;
        std::shared_ptr<DeviceResources> m_deviceResources; // cached pointer to device resources
        LonLatController^ m_controller;                     // maps input events to movement
        bool m_loadingComplete;                             // flags completion of asynchronous asset loading
        D3D11_VIEWPORT m_viewport;                          // cached screen viewport
        DirectX::XMFLOAT4X4 m_nativeProjection;             // projection matrix independent of screen orientation
        BasicTimer^ m_sunPositionTimer;                     // used to update the position of the sun
        // holds data for location thumbnail updates
        std::tuple<Forecast^, Windows::Storage::Streams::IRandomAccessStream^, concurrency::task_completion_event<void>> m_thumbnailUpdate;
        BasicTimer^ m_thumbnailUpdateTimer;                 // controls when thumbnail updates are made
        struct timer_signal {};
        std::unique_ptr<concurrency::timer<timer_signal>> m_updateUserPreferencesTimer; // used to periodically read the latest user preferences
        std::unique_ptr<concurrency::call<timer_signal>> m_updateUserPreferencesCall;   // used to periodically read the latest user preferences
        bool m_renderWeatherEffects;                        // cached user preference whether to render weather effects (e.g. clouds)
        bool m_renderStarfield;                             // cached user preference whether to render stars
        Windows::Globalization::Calendar^ m_calendar;       // calendar used for scratch work.
    };
}

